/* Classic Ladder Project */
/* Copyright (C) 2001-2009 Marc Le Douarain */
/* http://www.multimania.com/mavati/classicladder */
/* http://www.sourceforge.net/projects/classicladder */
/* July 2009 */
/* ------------------------- */
/* Log of events parametered */
/* ------------------------- */
/* This library is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU Lesser General Public */
/* License as published by the Free Software Foundation; either */
/* version 2.1 of the License, or (at your option) any later version. */

/* This library is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU */
/* Lesser General Public License for more details. */

/* You should have received a copy of the GNU Lesser General Public */
/* License along with this library; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#ifndef MODULE
#include <stdio.h>
#include <string.h>
#include <time.h>
#endif

#include "classicladder.h"
#include "global.h"
#include "log_events.h"

// TODO in files.c add binary log file of StrLog: LoadLog, SaveLog.
// TODO + see StartupCleanupEvent() after binary file loaded, and config gtk modified... (beware on the parameter value if offset modified...)

StrLog Log;
StrConfigEventLog ConfigEventLog[ NBR_CONFIG_EVENTS_LOG ]; 

unsigned char ListCurrentDefType[ NBR_CURRENT_DEFS_MAX ];
int ListCurrentDefParam[ NBR_CURRENT_DEFS_MAX ];

void InitLog( void )
{
	int Scan;
	StrConfigEventLog * pCfgEvtLog;
	Log.LastEvent = -1;
	Log.NbrEvents = 0;
	for( Scan=0; Scan<NBR_CONFIG_EVENTS_LOG; Scan++ )
	{
		pCfgEvtLog = &ConfigEventLog[ Scan ];
		pCfgEvtLog->FirstVarNum = -1;
		pCfgEvtLog->NbrVars = 0;
		pCfgEvtLog->EventType = 0;
		pCfgEvtLog->Symbol[ 0 ] = '\0';
		pCfgEvtLog->Text[ 0 ] = '\0';
	}
//test (no file for now...)
/*pCfgEvtLog = &ConfigEventLog[ 0 ];
pCfgEvtLog->FirstVarNum = 3;
pCfgEvtLog->NbrVars = 2;
pCfgEvtLog->EventType = 1;
strcpy( pCfgEvtLog->Symbol,"MFAIL");
strcpy( pCfgEvtLog->Text,"First default event label...");
pCfgEvtLog = &ConfigEventLog[ 1 ];
pCfgEvtLog->FirstVarNum = 40;
pCfgEvtLog->NbrVars = 1;
strcpy( pCfgEvtLog->Symbol,"TOTO");
strcpy( pCfgEvtLog->Text,"toto here label...");
*/
}

void AdvanceLast( void )
{
	Log.LastEvent++;
	if (Log.LastEvent>=NBR_EVENTS_IN_LOG)
		Log.LastEvent = 0;
}
char AdvanceInLog( void )
{
	char EventSlotFound = FALSE;
	// no problem if not reached the maxima
	if (Log.NbrEvents<NBR_EVENTS_IN_LOG)
	{
		Log.NbrEvents++;
		AdvanceLast( );
		EventSlotFound = TRUE;
	}
	else
	{
		StrEventLog * pEvent;
		int LoopSecurity = 0;
		do
		{
			AdvanceLast( );
			LoopSecurity++;
			pEvent = &Log.Event[ Log.LastEvent ];
			// verify here that we can not destroy this old event
			// because it is not finished...
			if ( pEvent->EndTime==0 )
			{
				pEvent->OldEventThatCouldNotBeDestroyed = TRUE;
			}
			else
			{
				// just in case, it wasn't the case before... ;-)
				pEvent->OldEventThatCouldNotBeDestroyed = FALSE;
			}
		}while( pEvent->OldEventThatCouldNotBeDestroyed && LoopSecurity<NBR_EVENTS_IN_LOG );
		if ( pEvent->OldEventThatCouldNotBeDestroyed==FALSE )
			EventSlotFound = TRUE;
	}
	return EventSlotFound;
}
TypeTime GetCurrentTime( void )
{
	return (TypeTime)time( NULL );
}

void CreateEventLog( int ConfigArrayNumber, int ParameterValue, char StartNewOne )
{
	TypeTime TimeNow = GetCurrentTime( );
	StrEventLog * pEvent;
	if ( StartNewOne )
	{
		// Create a new event
		int iIdEvent = 0;
		// value of last index ?
		if ( Log.NbrEvents>0 )
			iIdEvent = Log.Event[ Log.LastEvent ].iIdEvent;
		iIdEvent++;
		// Whaoowwhh so much logged!?
		if ( iIdEvent<=0 )
			iIdEvent = 1;

		// Go to next slot event available
		if ( AdvanceInLog( ) )
		{
printf("log a new\n");
			// Fill event datas
			pEvent = &Log.Event[ Log.LastEvent ];
			pEvent->iIdEvent = iIdEvent;
			pEvent->StartTime = TimeNow;
			pEvent->EndTime = 0; //means not finished !
			pEvent->ConfigArrayNum = ConfigArrayNumber;
			pEvent->Parameter = ParameterValue;
			pEvent->OldEventThatCouldNotBeDestroyed = FALSE;
		}
	}
	else
	{
		// End an event (first search for its start...)
		// It not event one even, the search is fast!
		if (Log.NbrEvents>0)
		{
			char FoundIt = FALSE;
			int NbrEventsRemaining = Log.NbrEvents;
			int ScanEvent = Log.LastEvent;
			do
			{
			    pEvent = &Log.Event[ ScanEvent ];
				// the same ? and not already disapeared ?
				if ( pEvent->ConfigArrayNum==ConfigArrayNumber && pEvent->Parameter==ParameterValue && pEvent->EndTime==0 )
					FoundIt = TRUE;
				NbrEventsRemaining--;
				ScanEvent--;
				if (ScanEvent<0)
					ScanEvent = NBR_EVENTS_IN_LOG-1;
			}
			while( !FoundIt && NbrEventsRemaining>0 );
			if (FoundIt)
			{
printf("log the end\n");
				// Fill event datas
				pEvent->EndTime = TimeNow;
			}
		}
	}
}

// enquire the vars that user want to log
// to immediately in WriteVar( ) know that VarStateChanged has to been called...
void InitVarsArrayLogTags( void )
{
	int ScanLogVar;
	int ScanConfigNum;
	StrConfigEventLog * pCfgEvtLog;
	//none to log for now...
	for( ScanLogVar=0; ScanLogVar<SIZE_VAR_ARRAY; ScanLogVar++ )
		LogVarArray[ ScanLogVar ] = 0;
	//set true the ones that must be logged
	for( ScanConfigNum=0; ScanConfigNum<NBR_CONFIG_EVENTS_LOG; ScanConfigNum++ )
	{
		pCfgEvtLog = &ConfigEventLog[ ScanConfigNum ];
		for( ScanLogVar=pCfgEvtLog->FirstVarNum; ScanLogVar<pCfgEvtLog->FirstVarNum+pCfgEvtLog->NbrVars; ScanLogVar++ )
			LogVarArray[ ScanLogVar ] = 1;
	}
}

//Type not used, see why in classicladder.h
void VarStateChanged( int Type, int Num, int NewStateValue )
{
	int ScanConfigNum = 0;
	char FoundIt = FALSE;
	StrConfigEventLog * pCfgEvtLog;
printf("state of var B%d changed\n", Num);
	do
	{
		pCfgEvtLog = &ConfigEventLog[ ScanConfigNum ];
		if ( pCfgEvtLog->FirstVarNum!=-1 && pCfgEvtLog->NbrVars>0 )
		{
			if ( pCfgEvtLog->FirstVarNum<=Num && Num<pCfgEvtLog->FirstVarNum+pCfgEvtLog->NbrVars )
				FoundIt = TRUE;
		}
		if ( !FoundIt )
			ScanConfigNum++;
	}
	while( ScanConfigNum<NBR_CONFIG_EVENTS_LOG && !FoundIt );
	if ( FoundIt )
	{
		int ParameterValue = -1;
		if ( pCfgEvtLog->NbrVars>1 )
			ParameterValue = Num-pCfgEvtLog->FirstVarNum;
printf("will now log it (param=%d)!\n",ParameterValue);
		CreateEventLog( ScanConfigNum, ParameterValue, NewStateValue );
		//Ask to update log window display !
		InfosGene->LogContentModified = TRUE;
		// if it is a default even type, ask to update the display list !
		if ( pCfgEvtLog->EventType>0 )
			InfosGene->DefaultLogListModified = TRUE;
	}
	else
	{
printf("var (%d/%d) not found in config log array... strange...\n",Type,Num);
	}
}


void CleanupEventsLog( void )
{
//TODO...
}

int FindCurrentDefaults( void )
{
	int NbrDefsFound = 0;
	StrEventLog * pEvent;
	StrConfigEventLog * pCfgEvtLog;
	if (Log.NbrEvents>0)
	{
		int NbrEventsRemaining = Log.NbrEvents;
		int ScanEvent = Log.LastEvent;
		do
		{
		    pEvent = &Log.Event[ ScanEvent ];
			pCfgEvtLog = &ConfigEventLog[ pEvent->ConfigArrayNum ];
			// not disapeared ? -and- is a default type ?
			if ( pEvent->EndTime==0 && pCfgEvtLog->EventType>0 )
			{
				ListCurrentDefType[ NbrDefsFound ] = pEvent->ConfigArrayNum;
				ListCurrentDefParam[ NbrDefsFound++ ] = pEvent->Parameter;
			}
			NbrEventsRemaining--;
			ScanEvent--;
			if (ScanEvent<0)
				ScanEvent = NBR_EVENTS_IN_LOG-1;
		}
		while( NbrEventsRemaining>0 && NbrDefsFound<NBR_CURRENT_DEFS_MAX );
	}
	return NbrDefsFound;
}


